﻿using DevExpress.Spreadsheet;

namespace EasyXaf.ExcelImporters;

public static class CellExtensions
{
    private static T GetNumericValue<T>(this Cell cell, out string error) where T : struct
    {
        error = null;

        var cellValue = cell.Value;

        if (cellValue.IsNumeric)
        {
            return (T)Convert.ChangeType(cellValue.NumericValue, typeof(T));
        }
        else if (cellValue.IsText)
        {
            var typedValue = NumericHelper.GetNumericValue<T>(cellValue.TextValue?.Trim());
            if (typedValue.HasValue)
            {
                return typedValue.Value;
            }
        }

        error = $"无法将{cellValue.TextValue}转换为{typeof(T).Name}类型";
        return default;
    }

    private static bool GetBooleanValue(this Cell cell, out string error)
    {
        error = null;

        var cellValue = cell.Value;

        if (cellValue.IsBoolean)
        {
            return cellValue.BooleanValue;
        }
        else if (cellValue.IsText)
        {
            if (bool.TryParse(cellValue.TextValue, out var boolean))
            {
                return boolean;
            }
        }

        error = $"无法将{cellValue.TextValue}转换为bool类型";
        return default;
    }

    private static Guid GetGuidValue(this Cell cell, out string error)
    {
        error = null;

        var cellValue = cell.Value;

        if (cellValue.IsText)
        {
            if (Guid.TryParse(cellValue.TextValue, out var guid))
            {
                return guid;
            }
        }

        error = $"无法将{cellValue.TextValue}转换为Guid类型";
        return default;
    }

    private static DateTime GetDateTimeValue(this Cell cell, out string error)
    {
        error = null;

        var cellValue = cell.Value;

        if (cellValue.IsDateTime)
        {
            return cellValue.DateTimeValue;
        }
        else if (cellValue.IsText)
        {
            if (DateTime.TryParse(cellValue.TextValue, out var dateTime))
            {
                return dateTime;
            }
        }

        error = $"无法将{cellValue.TextValue}转换为DateTime类型";
        return default;
    }

    private static TimeSpan GetTimeSpanValue(this Cell cell, out string error)
    {
        error = null;

        var cellValue = cell.Value;

        if (cellValue.IsText)
        {
            if (TimeSpan.TryParse(cellValue.TextValue, out var timeSpan))
            {
                return timeSpan;
            }
        }

        error = $"无法将{cellValue.TextValue}转换为TimeSpan类型";
        return default;
    }

    private static DateTimeOffset GetDateTimeOffsetValue(this Cell cell, out string error)
    {
        error = null;

        var cellValue = cell.Value;

        if (cellValue.IsText)
        {
            if (DateTimeOffset.TryParse(cellValue.TextValue, out var dateTimeOffset))
            {
                return dateTimeOffset;
            }
        }

        error = $"无法将{cellValue.TextValue}转换为DateTimeOffset类型";
        return default;
    }

    public static object GetCellValue(this Cell cell, Type dataType, out string error)
    {
        if (dataType == typeof(sbyte))
        {
            return GetNumericValue<sbyte>(cell, out error);
        }
        else if (dataType == typeof(byte))
        {
            return GetNumericValue<byte>(cell, out error);
        }
        else if (dataType == typeof(short))
        {
            return GetNumericValue<short>(cell, out error);
        }
        else if (dataType == typeof(ushort))
        {
            return GetNumericValue<ushort>(cell, out error);
        }
        else if (dataType == typeof(int))
        {
            return GetNumericValue<int>(cell, out error);
        }
        else if (dataType == typeof(uint))
        {
            return GetNumericValue<uint>(cell, out error);
        }
        else if (dataType == typeof(long))
        {
            return GetNumericValue<long>(cell, out error);
        }
        else if (dataType == typeof(ulong))
        {
            return GetNumericValue<ulong>(cell, out error);
        }
        else if (dataType == typeof(float))
        {
            return GetNumericValue<float>(cell, out error);
        }
        else if (dataType == typeof(double))
        {
            return GetNumericValue<double>(cell, out error);
        }
        else if (dataType == typeof(decimal))
        {
            return GetNumericValue<decimal>(cell, out error);
        }
        else if (dataType == typeof(bool))
        {
            return GetBooleanValue(cell, out error);
        }
        else if (dataType == typeof(Guid))
        {
            return GetGuidValue(cell, out error);
        }
        else if (dataType == typeof(DateTime))
        {
            return GetDateTimeValue(cell, out error);
        }
        else if (dataType == typeof(TimeSpan))
        {
            return GetTimeSpanValue(cell, out error);
        }
        else if (dataType == typeof(DateTimeOffset))
        {
            return GetDateTimeOffsetValue(cell, out error);
        }

        error = null;
        return null;
    }
}
